import pako from 'pako'
import { capital, translate } from '../../handleData'

/**
 * 识别变量类型
 * @return {string} 返回variable的类型: Number Or String Or Boolean Or Array Or Object Or Function Or Undefined Or Null Or Date Or RegExp Or Error
 */
function getTypeOfVariable(variable) {
  const str = Object.prototype.toString.call(variable)
  return str.substring(8, str.length - 1)
}

/**
 * 获取文件名后缀
 * @return {string} 后缀名（小写）
 */
function getFileExtension(path) {
  if (getTypeOfVariable(path) !== 'String') {
    console.error('文件路径非字符串', path)
  } else {
    try {
      if (path.lastIndexOf('.') === -1) return false
      else return path.substring(path.lastIndexOf('.') + 1, path.length).toLowerCase()
    } catch (e) {
      console.error('文件后缀名识别失败', e)
    }
  }
}

/**
 * 获取文件名
 * @return {string} 文件名
 */
function getFilenameFromPath(path) {
  if (getTypeOfVariable(path) !== 'String') {
    console.error('文件路径非字符串', path)
  } else {
    try {
      const start = path.lastIndexOf('\\')
      const end = path.lastIndexOf('.')
      return path.substring(start + 1, end)
    } catch (e) {
      console.error('文件读取失败', e)
    }
  }
}

/**
 * 模仿sleep
 * @millisecond {number} 暂停时间毫秒单位
 */
function sleep(millisecond) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, millisecond)
  })
}

/**
 * 对象字符串转对象
 * @string {string} JSON格式的字符串
 */
function string2object(string) {
  const type = typeof string
  if (type === 'string') {
    if (!isNaN(parseInt(string))) return string
    try {
      try {
        return JSON.parse(string)
      } catch (e) {
        console.error(e)
      }
      return (() => 'return ' + string)()
    } catch (e) {
      return string
    }
  } else {
    return string
  }
}

/**
 * 对象中每一字段字符串转对象
 * @string {string} 暂停时间毫秒单位
 */
function string2objectForObj(obj) {
  for (const i in obj) if (getTypeOfVariable(obj[i]) === 'String') obj[i] = string2object(obj[i])
  return obj
}

/**
 * 压缩字符串
 * @param {String} str 要压缩的字符串
 * @return {String} 字符串
 */
function jsonzip(str) {
  if (getTypeOfVariable(str) === 'String') str = JSON.stringify(str)
  pako.gzip(encodeURIComponent(str), { to: 'string' })
}

/**
 * 解压字符串
 * @param {String} gzip 要解压的数据
 * @return {String} 字符串
 */
function jsonunzip(gzip) {
  if (getTypeOfVariable(gzip) !== 'String') {
    console.error('解压的数据非字符串格式')
    return
  }
  JSON.parse(decodeURIComponent(pako.ungzip(gzip, { to: 'string' })))
}

function zero_fill_hex(num, digits) {
  let s = num.toString(16)
  while (s.length < digits) s = '0' + s
  return s
}

function rgb2hex(rgb) {
  if (!rgb) return '#ffffff'
  const decimal = Number(rgb[0]) * 65536 + Number(rgb[1]) * 256 + Number(rgb[2])
  return '#' + zero_fill_hex(decimal, 6)
}

//获取hex格式颜色
const getHexColor = rgb => rgb2hex(getTypeOfVariable(rgb) === 'Array' ? rgb : color256[rgb]).toLowerCase()

const isCollinear = (p1, p2, p3) => {
  const [x0, y0] = p1
  const [x1, y1] = p2
  const [x2, y2] = p3
  if ((x0 === x1 && y0 === y1) || (x2 === x1 && y2 === y1)) return false
  const l1 = (Math.atan((y1 - y0) / (x1 - x0)) * 180) / Math.PI
  const l2 = (Math.atan((y2 - y1) / (x2 - x1)) * 180) / Math.PI
  return Math.abs(l1 - l2) < 3
}

const isPolyline = ({ vertices: ids, docs, getLocationCoord }) => {
  const points = []
  const trueIds = []
  const truePoints = []
  if (ids.length < 2) return { truePoints, trueIds }
  for (let i = 0; i < ids.length; i++) {
    const id = ids[i]
    if (getLocationCoord) {
      const [x, y] = getLocationCoord(id)
      points.push([x, -y])
    } else {
      const [x, y] = docs[id].location
      points.push([Math.floor(x), Math.floor(-y)])
    }
  }

  const errPoints = []
  if (points.length > 2) {
    for (let i = 0; i < points.length; i++) {
      let p1, p2, p3
      if (i < points.length - 2) {
        p1 = points[i]
        p2 = points[i + 1]
        p3 = points[i + 2]
        if (isCollinear(p1, p2, p3, getLocationCoord)) errPoints.push(i + 1)
      }
      if (i === points.length - 2) {
        p1 = points[i]
        p2 = points[i + 1]
        p3 = points[0]
        if (isCollinear(p1, p2, p3, getLocationCoord)) errPoints.push(i + 1)
      }
      if (i === points.length - 1) {
        p1 = points[i]
        p2 = points[0]
        p3 = points[1]
        if (isCollinear(p1, p2, p3, getLocationCoord)) {
          truePoints.shift()
          trueIds.shift()
        }
      }
      if (!errPoints.includes(i)) {
        truePoints.push(points[i])
        trueIds.push(ids[i])
      }
    }
  } else {
    truePoints.push(points[0])
    truePoints.push(points[1])
    trueIds.push(ids[0])
    trueIds.push(ids[1])
  }
  return { truePoints, trueIds }
}

const getBounds = (data, zoom) => {
  const xArr = []
  const yArr = []
  data.cols.point.forEach(i => {
    xArr.push(i.location[0])
    yArr.push(i.location[1])
  })
  const maxX = Math.max(...xArr)
  const maxY = Math.max(...yArr)
  const minX = Math.min(...xArr)
  const minY = Math.min(...yArr)
  const narrowCoord = coord => Math.floor(coord / zoom)
  return {
    x: narrowCoord(minX),
    y: -narrowCoord(maxY),
    width: narrowCoord(maxX - minX),
    height: narrowCoord(maxY - minY)
  }
}

//首字母大写
const titleCase = str => str.toLowerCase().replace(/( |^)[a-z]/g, L => L.toUpperCase())

//获取url中的变量参数
const getQueryVariable = variable => {
  const query = window.location.search.substring(1)
  const vars = query.split('&')
  for (let i = 0; i < vars.length; i++) {
    const pair = vars[i].split('=')
    if (pair[0] === variable) {
      return pair[1]
    }
  }
  return false
}

const compare = function (a, b) {
  const checkKey = key => a[key] && key
  const key = checkKey('updatedAt') || checkKey('name') || checkKey('id') || checkKey('length')
  if (a[key] && b[key]) {
    if (a[key] < b[key]) {
      return -1
    } else if (a[key] > b[key]) {
      return 1
    } else if (a[key] === b[key] && key === 'updatedAt' && a.name && b.name) {
      let intA = a.name.match(/\d+/g)
      let intB = b.name.match(/\d+/g)
      if (intA) intA = +intA.join('')
      if (intB) intB = +intB.join('')
      if (intA < intB) {
        return -1
      } else if (intA > intB) {
        return 1
      } else {
        return 0
      }
    } else {
      return 0
    }
  } else {
    return 0
  }
}

// 判断点是否在多边形内部
// checkPoint的数据形式是一维数组: [591, 280]
// polygonPoints的数据形式是二位数组:  [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]
const isInPolygon = (checkPoint, polygonPoints) => {
  let counter = 0
  let i
  let xinters
  let p1, p2
  const pointCount = polygonPoints.length
  p1 = polygonPoints[0]

  for (i = 1; i <= pointCount; i++) {
    p2 = polygonPoints[i % pointCount]
    if (checkPoint[0] > Math.min(p1[0], p2[0]) && checkPoint[0] <= Math.max(p1[0], p2[0])) {
      if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
        if (p1[0] !== p2[0]) {
          xinters = ((checkPoint[0] - p1[0]) * (p2[1] - p1[1])) / (p2[0] - p1[0]) + p1[1]
          if (p1[1] === p2[1] || checkPoint[1] <= xinters) {
            counter++
          }
        }
      }
    }
    p1 = p2
  }
  if (counter % 2 === 0) {
    return false
  } else {
    return true
  }
}

const hashCode = input => {
  const I64BIT_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789da'.split('')

  let hash = 5381
  let i = input.length - 1

  if (typeof input === 'string') {
    for (; i > -1; i--) hash += (hash << 5) + input.charCodeAt(i)
  } else {
    for (; i > -1; i--) hash += (hash << 5) + input[i]
  }
  let value = hash & 0x7fffffff

  let retValue = ''
  do {
    retValue += I64BIT_TABLE[value & 0x3f]
  } while ((value >>= 6))

  return retValue.toLowerCase()
}

const isLayerExist = (key, data) => {
  const cols = data.cols
  if (!cols) return false
  const layer = cols.layer.find(i => i.type === capital(key))
  if (!layer) return false
  const lines = cols.line.filter(i => i.layer === layer.id)
  return !!lines.length
}

function colorHex(r, g, b) {
  return ((r << 16) | (g << 8) | b).toString(16)
}

const randomColor = () => {
  function rn(min, max) {
    return Math.floor(Math.random() * (max - min) + min)
  }
  const r = rn(50, 255)
  const g = rn(50, 255)
  const b = rn(0, 155)
  return '#' + colorHex(r, g, b)
}

const color256 = {
  1: [255, 0, 0],
  2: [255, 255, 0],
  3: [0, 255, 0],
  4: [0, 255, 255],
  5: [0, 0, 255],
  6: [255, 0, 255],
  7: [255, 255, 255],
  8: [128, 128, 128],
  9: [192, 192, 192],
  10: [255, 0, 0],
  11: [255, 127, 127],
  12: [204, 0, 0],
  13: [204, 102, 102],
  14: [153, 0, 0],
  15: [153, 76, 76],
  16: [127, 0, 0],
  17: [127, 63, 63],
  18: [76, 0, 0],
  19: [76, 38, 38],
  20: [255, 63, 0],
  21: [255, 159, 127],
  22: [204, 51, 0],
  23: [204, 127, 102],
  24: [153, 38, 0],
  25: [153, 95, 76],
  26: [127, 31, 0],
  27: [127, 79, 63],
  28: [76, 19, 0],
  29: [76, 47, 38],
  30: [255, 127, 0],
  31: [255, 191, 127],
  32: [204, 102, 0],
  33: [204, 153, 102],
  34: [153, 76, 0],
  35: [153, 114, 76],
  36: [127, 63, 0],
  37: [127, 95, 63],
  38: [76, 38, 0],
  39: [76, 57, 38],
  40: [255, 191, 0],
  41: [255, 223, 127],
  42: [204, 153, 0],
  43: [204, 178, 102],
  44: [153, 114, 0],
  45: [153, 133, 76],
  46: [127, 95, 0],
  47: [127, 111, 63],
  48: [76, 57, 0],
  49: [76, 66, 38],
  50: [255, 255, 0],
  51: [255, 255, 127],
  52: [204, 204, 0],
  53: [204, 204, 102],
  54: [153, 153, 0],
  55: [153, 153, 76],
  56: [127, 127, 0],
  57: [127, 127, 63],
  58: [76, 76, 0],
  59: [76, 76, 38],
  60: [191, 255, 0],
  61: [223, 255, 127],
  62: [153, 204, 0],
  63: [178, 204, 102],
  64: [114, 153, 0],
  65: [133, 153, 76],
  66: [95, 127, 0],
  67: [111, 127, 63],
  68: [57, 76, 0],
  69: [66, 76, 38],
  70: [127, 255, 0],
  71: [191, 255, 127],
  72: [102, 204, 0],
  73: [153, 204, 102],
  74: [76, 153, 0],
  75: [114, 153, 76],
  76: [63, 127, 0],
  77: [95, 127, 63],
  78: [38, 76, 0],
  79: [57, 76, 38],
  80: [63, 255, 0],
  81: [159, 255, 127],
  82: [51, 204, 0],
  83: [127, 204, 102],
  84: [38, 153, 0],
  85: [95, 153, 76],
  86: [31, 127, 0],
  87: [79, 127, 63],
  88: [19, 76, 0],
  89: [47, 76, 38],
  90: [0, 255, 0],
  91: [127, 255, 127],
  92: [0, 204, 0],
  93: [102, 204, 102],
  94: [0, 153, 0],
  95: [76, 153, 76],
  96: [0, 127, 0],
  97: [63, 127, 63],
  98: [0, 76, 0],
  99: [38, 76, 38],
  100: [0, 255, 63],
  101: [127, 255, 159],
  102: [0, 204, 51],
  103: [102, 204, 127],
  104: [0, 153, 38],
  105: [76, 153, 95],
  106: [0, 127, 31],
  107: [63, 127, 79],
  108: [0, 76, 19],
  109: [38, 76, 47],
  110: [0, 255, 127],
  111: [127, 255, 191],
  112: [0, 204, 102],
  113: [102, 204, 153],
  114: [0, 153, 76],
  115: [76, 153, 114],
  116: [0, 127, 63],
  117: [63, 127, 95],
  118: [0, 76, 38],
  119: [38, 76, 57],
  120: [0, 255, 191],
  121: [127, 255, 223],
  122: [0, 204, 153],
  123: [102, 204, 178],
  124: [0, 153, 114],
  125: [76, 153, 133],
  126: [0, 127, 95],
  127: [63, 127, 111],
  128: [0, 76, 57],
  129: [38, 76, 66],
  130: [0, 255, 255],
  131: [127, 255, 255],
  132: [0, 204, 204],
  133: [102, 204, 204],
  134: [0, 153, 153],
  135: [76, 153, 153],
  136: [0, 127, 127],
  137: [63, 127, 127],
  138: [0, 76, 76],
  139: [38, 76, 76],
  140: [0, 191, 255],
  141: [127, 223, 255],
  142: [0, 153, 204],
  143: [102, 178, 204],
  144: [0, 114, 153],
  145: [76, 133, 153],
  146: [0, 95, 127],
  147: [63, 111, 127],
  148: [0, 57, 76],
  149: [38, 66, 76],
  150: [0, 127, 255],
  151: [127, 191, 255],
  152: [0, 102, 204],
  153: [102, 153, 204],
  154: [0, 76, 153],
  155: [76, 114, 153],
  156: [0, 63, 127],
  157: [63, 95, 127],
  158: [0, 38, 76],
  159: [38, 57, 76],
  160: [0, 63, 255],
  161: [127, 159, 255],
  162: [0, 51, 204],
  163: [102, 127, 204],
  164: [0, 38, 153],
  165: [76, 95, 153],
  166: [0, 31, 127],
  167: [63, 79, 127],
  168: [0, 19, 76],
  169: [38, 47, 76],
  170: [0, 0, 255],
  171: [127, 127, 255],
  172: [0, 0, 204],
  173: [102, 102, 204],
  174: [0, 0, 153],
  175: [76, 76, 153],
  176: [0, 0, 127],
  177: [63, 63, 127],
  178: [0, 0, 76],
  179: [38, 38, 76],
  180: [63, 0, 255],
  181: [159, 127, 255],
  182: [51, 0, 204],
  183: [127, 102, 204],
  184: [38, 0, 153],
  185: [95, 76, 153],
  186: [31, 0, 127],
  187: [79, 63, 127],
  188: [19, 0, 76],
  189: [47, 38, 76],
  190: [127, 0, 255],
  191: [191, 127, 255],
  192: [102, 0, 204],
  193: [153, 102, 204],
  194: [76, 0, 153],
  195: [114, 76, 153],
  196: [63, 0, 127],
  197: [95, 63, 127],
  198: [38, 0, 76],
  199: [57, 38, 76],
  200: [191, 0, 255],
  201: [223, 127, 255],
  202: [153, 0, 204],
  203: [178, 102, 204],
  204: [114, 0, 153],
  205: [133, 76, 153],
  206: [95, 0, 127],
  207: [111, 63, 127],
  208: [57, 0, 76],
  209: [66, 38, 76],
  210: [255, 0, 255],
  211: [255, 127, 255],
  212: [204, 0, 204],
  213: [204, 102, 204],
  214: [153, 0, 153],
  215: [153, 76, 153],
  216: [127, 0, 127],
  217: [127, 63, 127],
  218: [76, 0, 76],
  219: [76, 38, 76],
  220: [255, 0, 191],
  221: [255, 127, 223],
  222: [204, 0, 153],
  223: [204, 102, 178],
  224: [153, 0, 114],
  225: [153, 76, 133],
  226: [127, 0, 95],
  227: [127, 63, 111],
  228: [76, 0, 57],
  229: [76, 38, 66],
  230: [255, 0, 127],
  231: [255, 127, 191],
  232: [204, 0, 102],
  233: [204, 102, 153],
  234: [153, 0, 76],
  235: [153, 76, 114],
  236: [127, 0, 63],
  237: [127, 63, 95],
  238: [76, 0, 38],
  239: [76, 38, 57],
  240: [255, 0, 63],
  241: [255, 127, 159],
  242: [204, 0, 51],
  243: [204, 102, 127],
  244: [153, 0, 38],
  245: [153, 76, 95],
  246: [127, 0, 31],
  247: [127, 63, 79],
  248: [76, 0, 19],
  249: [76, 38, 47],
  250: [51, 51, 51],
  251: [91, 91, 91],
  252: [132, 132, 132],
  253: [173, 173, 173],
  254: [214, 214, 214],
  255: [255, 255, 255],
  256: [255, 255, 255]
}

export {
  string2object,
  jsonzip,
  jsonunzip,
  string2objectForObj,
  getTypeOfVariable,
  getFileExtension,
  getFilenameFromPath,
  sleep,
  getHexColor,
  isCollinear,
  isPolyline,
  getBounds,
  titleCase,
  getQueryVariable,
  compare,
  isInPolygon,
  hashCode,
  isLayerExist,
  translate,
  randomColor
}
